// fstream standard header -*-c++-*-
// Copyright 2003-2010 IAR Systems AB. 
#ifndef _FSTREAM_
#define _FSTREAM_

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <istream>

#if !_DLIB_FILE_DESCRIPTOR
  #error "This library configuration does not support file I/O, either use \
another existing library configuration or define a new and rebuild the library."
#endif

/* Module consistency. */
#pragma rtmodel="__dlib_file_descriptor",_STRINGIFY(_DLIB_FILE_DESCRIPTOR)

_STD_BEGIN

extern __ATTRIBUTES _Filet *__iar_Fiopen(const char *, ios_base::openmode, int);
extern __ATTRIBUTES _Filet *__iar_Fiopen(const wchar_t *, ios_base::openmode, int);


                // CLASS filebuf
class filebuf
        : public streambuf
        {       // stream buffer associated with a C stream
public:
        typedef char _Elem;
        typedef char_traits _Traits;
        typedef filebuf _Myt;
        typedef _Traits::state_type _Myst;
        typedef streambuf _Mysb;

        virtual ~filebuf()
                {       // destroy the object
                if (_Closef)
                        close();
                }

        filebuf(_Filet *_File = 0)
                : _Mysb()
                {       // construct from pointer to C stream
                _Init(_File, _Newfl);
                }

        typedef _Traits::int_type int_type;
        typedef _Traits::pos_type pos_type;
        typedef _Traits::off_type off_type;

        filebuf(_Uninitialized)
                : _Mysb(_Noinit)
                {       // construct uninitialized
                }

        enum _Initfl
                {       // reasons for a call to _Init
                _Newfl, _Openfl, _Closefl};

        bool is_open() const
                {       // test if C stream has been opened
                return (_Myfile != 0);
                }

        _Myt *open(const char *_Filename,
                ios_base::openmode _Mode,
                int _Prot = (int)ios_base::_Openprot);

        _Myt *open(const char *_Filename, ios_base::open_mode _Mode);


        _Myt *close();


protected:
        virtual streamsize xsputn(const _Elem *_Ptr, streamsize _Count);

        virtual int_type overflow(int_type _Meta = _Traits::eof());


        virtual int_type pbackfail(int_type _Meta = _Traits::eof());


        virtual int_type underflow();


        virtual int_type uflow();


        virtual pos_type seekoff(off_type _Off, 
                ios_base::seekdir _Way,
                ios_base::openmode =
                        (ios_base::openmode)(ios_base::in | ios_base::out));


        virtual pos_type seekpos(pos_type _Pos,
                ios_base::openmode =
                        (ios_base::openmode)(ios_base::in | ios_base::out));

        virtual _Mysb *setbuf(_Elem *_Buffer, streamsize _Count);


        virtual int sync();


        virtual void imbue(const locale& _Loc)
                {       // set locale to argument (capture nontrivial codecvt facet)
                }

        void _Init(_Filet *_File, _Initfl _Which);


        bool _Endwrite()
                {       // dummy write wrapup (no shift states)
                return (true);
                }

private:
        _Traits::state_type _State;     // current conversion state
        bool _Closef;   // true if C stream must be closed
        _Filet *_Myfile;        // pointer to C stream
        };

                // CLASS ifstream
class ifstream
        : public istream
        {       // input stream associated with a C stream
public:
        typedef char _Elem;
        typedef char_traits _Traits;
        typedef ifstream _Myt;
        typedef filebuf _Myfb;
        typedef ios _Myios;

        ifstream()
                : istream(&_Filebuffer)
                {       // construct unopened
                }

        explicit ifstream(const char *_Filename,
                ios_base::openmode _Mode = ios_base::in,
                int _Prot = (int)ios_base::_Openprot)
                : istream(&_Filebuffer)
                {       // construct with named file and specified mode
                if (_Filebuffer.open(_Filename, _Mode | ios_base::in, _Prot) == 0)
                        setstate(failbit);
                }

        explicit ifstream(_Filet *_File)
                : istream(&_Filebuffer),
                        _Filebuffer(_File)
                {       // construct with specified C stream
                }
        virtual ~ifstream()
                {       // destroy the object
                }

        _Myfb *rdbuf() const
                {       // return pointer to file buffer
                return ((_Myfb *)&_Filebuffer);
                }

        bool is_open() const
                {       // test if C stream has been opened
                return (_Filebuffer.is_open());
                }

        void open(const char *_Filename,
                ios_base::openmode _Mode = ios_base::in,
                int _Prot = (int)ios_base::_Openprot)
                {       // open a C stream with specified mode
                if (_Filebuffer.open(_Filename, _Mode | ios_base::in, _Prot) == 0)
                        _Myios::setstate(ios_base::failbit);
                }

        void open(const char *_Filename, ios_base::open_mode _Mode)
                {       // open named file with specified mode (old style)
                open(_Filename, (ios_base::openmode)_Mode);
                }

        void close()
                {       // close the C stream
                if (_Filebuffer.close() == 0)
                        _Myios::setstate(ios_base::failbit);
                }

private:
        _Myfb _Filebuffer;      // the file buffer
        };

                // CLASS ofstream
class ofstream
        : public ostream
        {       // output stream associated with a C stream
public:
        typedef char _Elem;
        typedef char_traits _Traits;
        typedef ofstream _Myt;
        typedef filebuf _Myfb;
        typedef ios _Myios;

        ofstream()
                : ostream(&_Filebuffer)
                {       // construct unopened
                }

        explicit ofstream(const char *_Filename,
                ios_base::openmode _Mode = ios_base::out,
                int _Prot = (int)ios_base::_Openprot)
                : ostream(&_Filebuffer)
                {       // construct with named file and specified mode
                if (_Filebuffer.open(_Filename, _Mode | ios_base::out, _Prot) == 0)
                        setstate(failbit);
                }

        explicit ofstream(_Filet *_File)
                : ostream(&_Filebuffer),
                        _Filebuffer(_File)
                {       // construct with specified C stream
                }

        virtual ~ofstream()
                {       // destroy the object
                }

        _Myfb *rdbuf() const
                {       // return pointer to file buffer
                return ((_Myfb *)&_Filebuffer);
                }

        bool is_open() const
                {       // test if C stream has been opened
                return (_Filebuffer.is_open());
                }

        void open(const char *_Filename,
                ios_base::openmode _Mode = ios_base::out,
                int _Prot = (int)ios_base::_Openprot)
                {       // open a C stream with specified mode
                if (_Filebuffer.open(_Filename, _Mode | ios_base::out, _Prot) == 0)
                        _Myios::setstate(ios_base::failbit);
                }

        void open(const char *_Filename, ios_base::open_mode _Mode)
                {       // open a C stream with specified mode (old style)
                open(_Filename, (ios_base::openmode)_Mode);
                }

        void close()
                {       // close the C stream
                if (_Filebuffer.close() == 0)
                        _Myios::setstate(ios_base::failbit);
                }

private:
        _Myfb _Filebuffer;      // the file buffer
        };
_STD_END

#endif /* _FSTREAM_ */

/*
 * Copyright (c) 1992-2009 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
V5.04:0576 */
